<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    * {
        margin: 0;
        padding: 0;
    }
    .canvas-container, .canvas2-container {
        display: none;
        border: 1px solid #ddd;
    }
</style>


<body>
    <div>
        <input type="file" id="imageFile" accept="image/*">
    </div>
    <div class="canvas-container">
        <canvas id="can"></canvas>
    </div>
    <!-- 保存canvas图片 -->

    <div class="canvas2-container">
        <canvas id="can2"></canvas>
    </div>
    <script>
        const oContainer = document.querySelector(".canvas-container");
        const oContainer2 = document.querySelector(".canvas2-container");

        const oImageFile = document.querySelector("#imageFile");

        const oCan = document.getElementById("can");
        const ctx = oCan.getContext("2d");

        const oCan2 = document.getElementById("can2");
        const ctx2 = oCan2.getContext("2d");

        const oImage = new Image();
        let initPos=[]
        const MASK_OPACITY = 0.5;
        let screenShotData=[]

        const init = () => {
            bindEvent()
        }
        init();

        function bindEvent(e) {
            oImageFile.addEventListener("change", handleFileChange, false);
            oCan.addEventListener("mousedown", handleCanvasMouseDown, false);
        }
        function handleCanvasMouseDown(e) {
            initPos=[e.offsetX,e.offsetY]
            oCan.addEventListener("mousemove", handleCanvasMouseMove, false);
            oCan.addEventListener("mouseup", handleCanvasMouseUp, false);
        }
        function handleCanvasMouseMove(e) {
           const endX = e.offsetX;
            const endY = e.offsetY;
            const [startX, startY] = initPos;
            const reactWidth = endX - startX;
            const reactHeight = endY - startY;
            const {width, height} = oCan;

            screenShotData =[startX, startY, reactWidth, reactHeight]

           ctx.clearReact(0, 0, width, height);
            drawImageMask(0, 0, width,height, MASK_OPACITY);
            drawScreenShot(width, height,reactWidth, reactHeight)

           
        }
        function handleCanvasMouseUp(e) {
            oCan.removeEventListener("mousemove", handleCanvasMouseMove, false);
            oCan.removeEventListener("mouseup", handleCanvasMouseUp, false);
            drawScreenShotImage(screenShotData)
        }
        function handleFileChange(e) {
            const file = e.target.files[0];
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = (e) => {

                const data = e.target.result;
             
                oImage.src = data;
                oImage.onload = function () {
                   const{width, height} = this
                   
                    generateCanvas(oContainer, oCan, width, height);
                    ctx.drawImage(oImage, 0, 0, width, height);
                    drawImageMask(0, 0, width, height, MASK_OPACITY);
                }
            }
        }
        function generateCanvas(container,canvas,width,height) {
          
            container.style.width = width + "px";
            container.style.height = height + "px";
            canvas.width = width;
            canvas.height = height;
            container.style.block='block';
        }
        function drawImageMask(x,y,width,height,opacity) {
            ctx.fillStyle = "rgba(0, 0, 0," + opacity + ")";
            ctx.fillRect(x, y, width, height);
        }
        function drawScreenShot(canWidth, canHeight,reactWidth, reactHeight) {
            // 当前图形的外绘制
            ctx.globalCompositeOperation = "destination-out";
            ctx.fillStyle = "#000"; // 不重要，过度层
            ctx.fillRect(...initPos, reactWidth, reactHeight);

            ctx.globalCompositeOperation = "destination-over";
            // 0, 0, canWidth, canHeight 图形大小
            ctx.drawImage(oImage, 0, 0, canWidth, canHeight,0,0,canWidth, canHeight);
        }   
        function drawScreenShotImage(screenShotData) {
            const data = ctx.getImageData(...screenShotData);
            generateCanvas(oContainer2, oCan2, screenShotData[2],screenShotData[3]);
            ctx2.clearReac(...screenShotData)
            ctx2.putImageData(data,0,0);
        }
    </script>
</body>

</html>